﻿using Common;
using NewDevice.USB;
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Packaging;
using System.IO.Ports;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using OfficeOpenXml.FormulaParsing.Exceptions;
using static OfficeOpenXml.ExcelErrorValue;

namespace IP20.Procdure
{
    internal class TestModule
    {
        public List<TestItem> TestItems { get; set; }
        private Dictionary<string, Func<TestItem, bool>> TestFuncs { get; set; }
        private static readonly object _locker = new object();
        private int stationIndex = 0;
        internal Action<string> ActionSetLog;

        /// <summary>
        /// 触发急停或安全光幕时结束
        /// </summary>
        public bool IsBreak { get; set; }

        public void ParseExcelFile(string path)
        {
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            if (!File.Exists(path))
            {
                throw new FileNotFoundException(path);
            }
            using (ExcelPackage package = new ExcelPackage(path))
            {
                ExcelWorksheet wsTestProcdure = package.Workbook.Worksheets["测试流程"];
                ExcelWorksheet wsConfig = package.Workbook.Worksheets["测试配置"];

                LoadTestProcdure(wsTestProcdure);
                LoadConfig(wsConfig);
            }
        }

        private static Dictionary<string, string> Params { get; set; }

        public static string GetParams(string key)
        {
            if (Params.Keys.Contains(key))
            {
                return Params[key];
            }
            throw new Exception($"未找到[{key}]配置项");
        }

        private void LoadConfig(ExcelWorksheet wsConfig)
        {
            Params = new Dictionary<string, string>();
            int row = 1;
            while (true)
            {
                ExcelRangeBase cell1 = wsConfig.Cells[row, 1];
                ExcelRangeBase cell2 = wsConfig.Cells[row, 2];
                if (cell1.Value == null)
                {
                    break;
                }
                if (string.IsNullOrEmpty(cell1.Value.ToString().Trim(' ')))
                {
                    break;
                }
                string key = cell1.Value.ToString().Trim(' ');

                string value = cell2.Value.ToString().Trim(' ');

                Params.Add(key, value);
                row++;
            }
        }

        private void LoadTestProcdure(ExcelWorksheet ws)
        {
            TestItems = new List<TestItem>();
            int row = 2;
            while (true)
            {
                ExcelRangeBase cell1 = ws.Cells[row, 1];
                ExcelRangeBase cell2 = ws.Cells[row, 2];
                ExcelRangeBase cell3 = ws.Cells[row, 3];
                ExcelRangeBase cell4 = ws.Cells[row, 4];
                ExcelRangeBase cell5 = ws.Cells[row, 5];
                ExcelRangeBase cell6 = ws.Cells[row, 6];
                ExcelRangeBase cell7 = ws.Cells[row, 7];
                ExcelRangeBase cell8 = ws.Cells[row, 8];
                ExcelRangeBase cell9 = ws.Cells[row, 9];
                ExcelRangeBase cell10 = ws.Cells[row, 10];
                ExcelRangeBase cell11 = ws.Cells[row, 11];
                ExcelRangeBase cell12 = ws.Cells[row, 12];
                ExcelRangeBase cell13 = ws.Cells[row, 13];
                ExcelRangeBase cell14 = ws.Cells[row, 14];

                if (cell1.Value == null)
                {
                    break;
                }
                if (string.IsNullOrEmpty(cell1.Value.ToString().Trim(' ')))
                {
                    break;
                }
                TestItem testItem = new TestItem();
                testItem.No = Convert.ToInt32(cell1.Value.ToString().Trim(' '));
                testItem.GroupNo = Convert.ToInt32(cell2.Value.ToString().Trim(' '));
                testItem.Item = cell3.Value?.ToString();
                testItem.Type = cell6.Value?.ToString().Trim(' ');
                testItem.OperationFun = cell7.Value?.ToString();
                testItem.Operator = cell8.Value?.ToString();
                testItem.Param1 = cell9.Value?.ToString();
                testItem.Param2 = cell10.Value?.ToString();
                testItem.Param3 = cell11.Value?.ToString();
                testItem.Param4 = cell12.Value?.ToString();
                testItem.Param5 = cell13.Value?.ToString();
                testItem.Param6 = cell14.Value?.ToString();
                testItem.Desc = cell3.Value?.ToString();
                testItem.Result = null;
                testItem.Message = null;
                testItem.BreakIfErr = cell4.Value?.ToString() == "1" ? true : false;
                testItem.IsChecked = cell5.Value?.ToString() == "1" ? true : false;
                if (testItem.Type == "测试")
                {
                    if (string.IsNullOrEmpty(testItem.Operator))
                    {
                        ;
                    }
                    else if (testItem.Operator == "Range")
                    {
                        testItem.PassCondition = $"{testItem.Param1}～{testItem.Param2}";
                    }
                    else if (testItem.Operator == "NotRange")
                    {
                        testItem.PassCondition = $"<={testItem.Param1}||>={testItem.Param2}";
                    }
                    else
                    {
                        testItem.PassCondition = $"{testItem.Operator}{testItem.Param1}";
                    }
                }
                if (!TestFuncs.ContainsKey(testItem.OperationFun))
                {
                    throw new Exception($"测试方法未找到[{testItem.OperationFun}]");
                }
                testItem.Excute = TestFuncs[testItem.OperationFun];
                TestItems.Add(testItem);
                row++;
            }
        }

        public TestModule(int stationIndex)
        {
            this.stationIndex = stationIndex;
            TestFuncs = new Dictionary<string, Func<TestItem, bool>>();

            // IT6302 系列
            TestFuncs.Add("IT6302SetVol", IT6302SetVol);
            TestFuncs.Add("IT6302SetCur", IT6302SetCur);
            TestFuncs.Add("IT6302Outp", IT6302Outp);
            TestFuncs.Add("IT6302AllOutp", IT6302AllOutp);
            TestFuncs.Add("IT6302MeasVol", IT6302MeasVol);
            TestFuncs.Add("IT6302MeasCur", IT6302MeasCur);

            // RU12 系列
            TestFuncs.Add("RU12SetVol", RU12SetVol);
            TestFuncs.Add("RU12SetCur", RU12SetCur);
            TestFuncs.Add("RU12Outp", RU12Outp);
            TestFuncs.Add("RU12MeasVol", RU12MeasVol);
            TestFuncs.Add("RU12MeasCur", RU12MeasCur);

            // PQW 数字IO 系列
            TestFuncs.Add("PQW16SetOffAll", PQW16SetOffAll);
            TestFuncs.Add("PQW16SetDO", PQW16SetDO);
            TestFuncs.Add("PQW16GetDI", PQW16GetDI);
            TestFuncs.Add("PQW8SetOffAll", PQW8SetOffAll);
            TestFuncs.Add("PQW8SetDO", PQW8SetDO);
            TestFuncs.Add("PQW8GetDI", PQW8GetDI);

            // JX1000 传感器 系列
            TestFuncs.Add("JX1000GetLight", JX1000GetLight);
            TestFuncs.Add("JX1000GetColor", JX1000GetColor);
            TestFuncs.Add("JX1000GetFreq", JX1000GetFreq);
            TestFuncs.Add("JX1000GetLightBulin", JX1000GetLightBulin);
            TestFuncs.Add("JX1000GetColorBulin", JX1000GetColorBulin);
            TestFuncs.Add("JX1000GetFreqBulin", JX1000GetFreqBulin);

            // 通用模拟量测量
            TestFuncs.Add("AnalogMeasVol", AnalogMeasVol);
            TestFuncs.Add("AnalogMeasCur", AnalogMeasCur);
            TestFuncs.Add("AnalogMeasCurNPN", AnalogMeasCurNPN);

            TestFuncs.Add("Delay", Delay);
            TestFuncs.Add("DL3021ASetMode", DL3021ASetMode);
            TestFuncs.Add("DL3021ASetVol", DL3021ASetVol);
            TestFuncs.Add("DL3021ASetCur", DL3021ASetCur);
            TestFuncs.Add("DL3021ASetRes", DL3021ASetRes);
            TestFuncs.Add("DL3021ASetPow", DL3021ASetPow);
            TestFuncs.Add("DL3021AMeasVol", DL3021AMeasVol);
            TestFuncs.Add("DL3021AMeasCur", DL3021AMeasCur);
            TestFuncs.Add("DL3021AMeasPow", DL3021AMeasPow);
            TestFuncs.Add("DL3021ASetStatus", DL3021ASetStatus);

            //IP20通信设置
            TestFuncs.Add("IP20SetLed", IP20SetLed);
            TestFuncs.Add("IP20Connect", IP20Connect);
            TestFuncs.Add("IP20ScanDevice", IP20ScanDevice);
            TestFuncs.Add("IP20WriteSN", IP20WriteSN);
            TestFuncs.Add("IP20ReadSN", IP20ReadSN);
            TestFuncs.Add("IP20ReadSnMac", IP20ReadSnMac);
            TestFuncs.Add("IP20EnterTestMode", IP20EnterTestMode);
            TestFuncs.Add("IP20ExitTestMode", IP20ExitTestMode);
            TestFuncs.Add("IP20Close", IP20Close);

            //TestFuncs.Add("JFlash", JFlash);
            TestFuncs.Add("WriteFlash", WriteFlash);

            TestFuncs.Add("ADSConnect", ADSConnect);
            TestFuncs.Add("ADSGetDI", ADSGetDI);
            TestFuncs.Add("ADSSetDO", ADSSetDO);
            TestFuncs.Add("ADSSetAO", ADSSetAO);
            TestFuncs.Add("ADSGetAI", ADSGetAI);
            TestFuncs.Add("ADSClose", ADSClose);

            TestFuncs.Add("PQW16SetDOForPower", PQW16SetDOForPower);
            TestFuncs.Add("CompareTemperature", CompareTemperature);

            //jq89314阻值转温度
            TestFuncs.Add("Jq89314ReadTemp", Jq89314ReadTemp);

            TestFuncs.Add("Jq89313ADSGetAI", Jq89313ADSGetAI);
            TestFuncs.Add("Jq89314ADSGetAI", Jq89314ADSGetAI);
        }

        private bool Jq89314ADSGetAI(TestItem arg)
        {
            int ch = int.Parse(arg.Param3);
            var min = (Global.Jq1314Config.GetParams($"Jq89314工位{stationIndex + 1}通道{ch}电压点检值下限"));
            var max = (Global.Jq1314Config.GetParams($"Jq89314工位{stationIndex + 1}通道{ch}电压点检值上限"));
            arg.Param1 = min.ToString();
            arg.Param2 = max.ToString();
            arg.PassCondition = $"({min}～{max})";
            var ret = TwinCatTool.GetAI<Int16>(stationIndex, 16);

            string msg = $"通道值:{ret[ch - 1]}";
            arg.Message = msg;

            return CompareValue(arg, ret[ch - 1]);
        }

        private bool Jq89313ADSGetAI(TestItem arg)
        {
            int ch = int.Parse(arg.Param3);
            var min = (Global.Jq1314Config.GetParams($"Jq89313工位{stationIndex + 1}通道{ch}电阻点检值下限"));
            var max = (Global.Jq1314Config.GetParams($"Jq89313工位{stationIndex + 1}通道{ch}电阻点检值上限"));
            arg.Param1 = min.ToString();
            arg.Param2 = max.ToString();
            arg.PassCondition = $"({min}～{max})";
            var ret = TwinCatTool.GetAI<Int16>(stationIndex, 16);

            string msg = $"通道值:{ret[ch - 1]}";
            arg.Message = msg;
            return CompareValue(arg, (double)(ret[ch - 1]));
        }

        private bool WriteFlash(TestItem item)
        {
            var xiWeiFlash = Global.ListXiWeiFlash[stationIndex];
            string fileName = item.Param3 + ".ware";
            var infos = xiWeiFlash.FlashInfos.Where(x => x.FlashName.Contains(fileName)).ToArray();
            if (infos.Count() != 1)
            {
                throw new Exception($"编程器查询到[{infos.Count()}]个文件,文件名[{fileName}]");
            }
            xiWeiFlash.SelectFlash(infos[0].FlashNo);
            var result = xiWeiFlash.StartFlash();
            item.Message = "烧录校验" + (result ? "成功" : "失败");

            return result;
        }

        private bool Jq89314ReadTemp(TestItem item)
        {
            using var serialPort = new AsciiSerialPort(Global.IP20Ports[stationIndex], 115200);

            serialPort.Open();

            serialPort.SendAsciiString("jqshell\n");
            serialPort.SendAsciiString("rpc 0 jq_tc_sensor showExtcj\n");
            Thread.Sleep(500);
            string response = serialPort.ReadExistingAsciiString(1000);

            serialPort.Close();

            ActionSetLog.Invoke(response);
            var index = response.IndexOf("extcjok");
            if (index <= 0)
            {
                throw new Exception($"串口返回数据异常");
            }

            double value = double.Parse(response.Substring(index).Split(',')[0].Split('_')[1]) / 100;

            item.Message = $"实测温度{value}℃";

            int ch = 4;
            var min = (Global.Jq1314Config.GetParams($"Jq89314工位{stationIndex + 1}通道{ch}电阻点检值下限"));
            var max = (Global.Jq1314Config.GetParams($"Jq89314工位{stationIndex + 1}通道{ch}电阻点检值上限"));
            item.Param1 = min.ToString();
            item.Param2 = max.ToString();
            item.PassCondition = $"({min}～{max})";

            return CompareValue(item, value);
        }

        private bool CompareTemperature(TestItem item)
        {
            List<double> temps;
            lock (_locker)
            {
                temps = Global.TempCard.GetValue();
            }
            //var tempsDiff = Math.Round((Math.Abs(temps[2] - temps[0]) + Math.Abs(temps[2] - temps[1])) / 2, 2);
            //item.Message = $"内外温度差{tempsDiff}℃";
            //return CompareValue(item, tempsDiff);
            item.Message = $"温度读值[{temps[0]}]";
            return CompareValue(item, temps[0]);
        }

        private bool ADSGetAI(TestItem item)
        {
            List<int> channels = item.Param3.Split(',')
                                    .Select(s => int.Parse(s.Trim()))
                                    .ToList();

            var ret = TwinCatTool.GetAI<Int16>(stationIndex, 16);

            string msg = "通道值:";
            bool result = true;
            for (int i = 0; i < channels.Count; i++)
            {
                var value = ret[channels[i] - 1];
                msg += $"{value},";

                if (!CompareValue(item, value))
                {
                    result = false;
                }
            }
            item.Message = msg.TrimEnd(',');
            return result;
        }

        private bool ADSSetAO(TestItem item)
        {
            //List<int> channels = item.Param3.Split(',')
            //                        .Select(s => int.Parse(s.Trim()))
            //                        .ToList();

            var values = item.Param3.Split(',')
                                    .Select(s => Int16.Parse(s.Trim()))
                                    .ToArray();

            TwinCatTool.SetAO(stationIndex, values);
            //if (channels.Count != values.Count())
            //{
            //    throw new Exception("通道数量与元素数量不符");
            //}

            //for (int i = 0; i < channels.Count; i++)
            //{
            //    TwinCatTool.SetAO(stationIndex, channels[i] - 1, values[i]);
            //}
            return true;
        }

        private bool ADSClose(TestItem item)
        {
            TwinCatTool.Close();
            return true;
        }

        private bool ADSSetDO(TestItem item)
        {
            List<int> channels = item.Param3.Split(',')
                                    .Select(s => int.Parse(s.Trim()))
                                    .ToList();
            bool v = item.Param4 == "1";
            bool[] values = new bool[16];
            for (int i = 0; i < values.Count(); i++)
            {
                values[i] = !v;
            }
            for (int i = 0; i < channels.Count; i++)
            {
                values[channels[i] - 1] = v;
            }

            TwinCatTool.SetDO(stationIndex, values);
            return true;
        }

        private bool ADSGetDI(TestItem item)
        {
            List<int> channels = item.Param3.Split(',')
                                    .Select(s => int.Parse(s.Trim()))
                                    .ToList();
            bool v = item.Param1 == "1";

            var ret = TwinCatTool.GetDI(stationIndex, 16);
            //for (int i = 0; i < ret.Count(); i++)
            //{
            //    if (i == )
            //    {
            //    }
            //}
            string msg = "通道状态:";
            bool result = true;
            for (int i = 0; i < channels.Count; i++)
            {
                var value = ret[channels[i] - 1];
                msg += $"{value},";
                if (value != v)
                {
                    result = false;
                }
            }
            item.Message = msg;
            return result;
        }

        private bool ADSConnect(TestItem item)
        {
            TwinCatTool.Connect();
            return true;
        }

        private bool JFlash(TestItem item)
        {
            string binFile = item.Param3;
            bool onlyErase = item.Param4.ToLower() == "0";
            ActionSetLog.Invoke($"工位[{stationIndex + 1}]JFlash开始");

            var result = JLink.JLink_Commander(Global.JFlashExePath, binFile, Global.ListJLinkSN[stationIndex], onlyErase: onlyErase);

            ActionSetLog.Invoke($"工位[{stationIndex + 1}]JFlash结束");

            return result;
        }

        private bool IP20Close(TestItem item)
        {
            var name = item.Param3;
            Global.IP20Factorys[stationIndex].Close();
            return true;
        }

        private bool IP20ExitTestMode(TestItem item)
        {
            var name = item.Param3;
            Global.IP20Factorys[stationIndex].ExitTestMode(name);

            return true;
        }

        private bool IP20EnterTestMode(TestItem item)
        {
            var name = item.Param3;
            Global.IP20Factorys[stationIndex].EnterTestMode(name);

            return true;
        }

        private bool IP20ReadSN(TestItem item)
        {
            var name = item.Param3;
            string sn;
            bool ret;
            (ret, sn, _) = Global.IP20Factorys[stationIndex].ReadSN(name);

            item.Message = $"反读SN={sn}";
            return ret;
        }

        private bool IP20ReadSnMac(TestItem item)
        {
            var name = item.Param3;
            string sn, mac;
            bool ret;
            (ret, sn, mac) = Global.IP20Factorys[stationIndex].ReadSN(name);

            item.Message = $"反读SN={sn},Mac={mac}";
            return ret && mac.TrimEnd(' ') != "" && mac.TrimEnd(' ') != "00:00:00:00:00:00:";
        }

        private bool IP20WriteSN(TestItem item)
        {
            var name = item.Param3;
            Global.IP20Factorys[stationIndex].WriteSN(name);
            return true;
        }

        private bool IP20ScanDevice(TestItem item)
        {
            Global.IP20Factorys[stationIndex].ScanDevice();

            return true;
        }

        private bool IP20Connect(TestItem item)
        {
            var name = item.Param3;
            Global.IP20Factorys[stationIndex].Connect();
            return true;
        }

        private bool IP20SetLed(TestItem item)
        {
            var name = item.Param3;
            var ledIndex = byte.Parse(item.Param4);
            var color = (FactroyLedColor)int.Parse(item.Param5);
            var offOn = byte.Parse(item.Param6);
            Global.IP20Factorys[stationIndex].SetLed(name, ledIndex, color, offOn);

            return true;
        }

        // ============== IT6302 系列函数 ==============
        private bool IT6302SetVol(TestItem item)
        {
            // 在这里实现IT6302设置电压的具体逻辑
            int channel = int.Parse(item.Param3);
            double value = double.Parse(item.Param4);
            Global.ListIT6302[stationIndex].SetVoltage(channel, value);
            return true;
        }

        private bool IT6302SetCur(TestItem item)
        {
            // 实现设置电流逻辑
            int channel = int.Parse(item.Param3);
            double value = double.Parse(item.Param4);
            Global.ListIT6302[stationIndex].SetCurrent(channel, value);
            return true;
        }

        private bool IT6302Outp(TestItem item)
        {
            // 实现输出控制逻辑
            int channel = int.Parse(item.Param3);
            int value = int.Parse(item.Param4);
            Global.ListIT6302[stationIndex].SetOutputStatus(channel, value == 1);
            return true;
        }

        private bool IT6302AllOutp(TestItem item)
        {
            // 实现输出控制逻辑;
            int value = int.Parse(item.Param3);
            Global.ListIT6302[stationIndex].SetOutputStatus(value == 1);
            return true;
        }

        private bool CompareValue(TestItem item, double value)
        {
            //ActionSetLog.Invoke($"PASS条件{item.PassCondition},实测值{value}");
            switch (item.Operator)
            {
                case "NotRange":
                    {
                        double cmpVal1 = Convert.ToDouble(item.Param1);
                        double cmpVal2 = Convert.ToDouble(item.Param2);
                        double min = Math.Min(cmpVal1, cmpVal2);
                        double max = Math.Max(cmpVal1, cmpVal2);
                        return value >= max || value <= min;
                    }

                case "Range":
                    {
                        double cmpVal1 = Convert.ToDouble(item.Param1);
                        double cmpVal2 = Convert.ToDouble(item.Param2);
                        double min = Math.Min(cmpVal1, cmpVal2);
                        double max = Math.Max(cmpVal1, cmpVal2);
                        return value >= min & value <= max;
                    }

                case ">=":
                    double cmpVal = Convert.ToDouble(item.Param1);
                    return value >= cmpVal;

                case ">":
                    cmpVal = Convert.ToDouble(item.Param1);
                    return value > cmpVal;

                case "<=":
                    cmpVal = Convert.ToDouble(item.Param1);
                    return value <= cmpVal;

                case "<":
                    cmpVal = Convert.ToDouble(item.Param1);
                    return value < cmpVal;

                default:
                    return false;
            }
        }

        private bool CompareValue(TestItem item, int value)
        {
            switch (item.Operator)
            {
                case "NotRange":
                    {
                        int cmpVal1 = Convert.ToInt32(item.Param1);
                        int cmpVal2 = Convert.ToInt32(item.Param2);
                        int min = Math.Min(cmpVal1, cmpVal2);
                        int max = Math.Max(cmpVal1, cmpVal2);
                        return value <= min || value >= max;
                    }
                case "Range":
                    {
                        int cmpVal1 = Convert.ToInt32(item.Param1);
                        int cmpVal2 = Convert.ToInt32(item.Param2);
                        int min = Math.Min(cmpVal1, cmpVal2);
                        int max = Math.Max(cmpVal1, cmpVal2);
                        return value >= min & value <= max;
                    }

                case ">=":
                    int cmpVal = Convert.ToInt32(item.Param1);
                    return value >= cmpVal;

                case ">":
                    cmpVal = Convert.ToInt32(item.Param1);
                    return value > cmpVal;

                case "<=":
                    cmpVal = Convert.ToInt32(item.Param1);
                    return value <= cmpVal;

                case "<":
                    cmpVal = Convert.ToInt32(item.Param1);
                    return value < cmpVal;

                default:
                    return false;
            }
        }

        private bool IT6302MeasVol(TestItem item)
        {
            // 实现测量电压逻辑
            int channel = int.Parse(item.Param3);
            var value = Global.ListIT6302[stationIndex].MeasVoltage(channel);
            double errorDiff = double.Parse(GetParams($"工位{stationIndex + 1}IT6302通道{channel}电压读值误差"));   //工位1IT6302通道1电压读值误差

            item.Message = $"实测值[{value}V],矫正值[{value + errorDiff}V]";
            return CompareValue(item, value + errorDiff);
        }

        private bool IT6302MeasCur(TestItem item)
        {
            // 实现测量电流逻辑
            int channel = int.Parse(item.Param3);
            var value = Global.ListIT6302[stationIndex].MeasCurrent(channel);

            double errorDiff = double.Parse(GetParams($"工位{stationIndex + 1}IT6302通道{channel}电流读值误差"));   //工位1IT6302通道1电流读值误差

            item.Message = $"实测值[{value}A],矫正值[{value + errorDiff}A]";

            return CompareValue(item, value + errorDiff);
        }

        // ============== RU12 系列函数 ==============
        private bool RU12SetVol(TestItem item)
        {
            // 实现RU12设置电压逻辑
            double value = double.Parse(item.Param3);
            Global.ListRUPower[stationIndex].SetVoltage(value);
            return true;
        }

        private bool RU12SetCur(TestItem item)
        {
            // 实现RU12设置电流逻辑
            double value = double.Parse(item.Param3);
            Global.ListRUPower[stationIndex].SetCurrent(value);
            return true;
        }

        private bool RU12Outp(TestItem item)
        {
            // 实现RU12输出控制逻辑
            int value = int.Parse(item.Param3);
            Global.ListRUPower[stationIndex].SetStatus(value == 1);
            return true;
        }

        private bool RU12MeasVol(TestItem item)
        {
            // 实现RU12测量电压逻辑
            var value = Global.ListRUPower[stationIndex].MeasVoltage();

            var valueDiff = double.Parse(GetParams($"工位{stationIndex + 1}RU-12-3040电压读值误差")); //工位1RU-12-3040电压读值误差

            item.Message = $"实测值[{value}V],矫正值[{value + valueDiff}V]";
            return CompareValue(item, value + valueDiff);
        }

        private bool RU12MeasCur(TestItem item)
        {
            // 实现RU12测量电流逻辑
            var value = Global.ListRUPower[stationIndex].MeasCurrent();

            var valueDiff = double.Parse(GetParams($"工位{stationIndex + 1}RU-12-3040电流读值误差")); //工位1RU-12-3040电压读值误差

            item.Message = $"实测值[{value}A],矫正值[{value + valueDiff}A]";
            return CompareValue(item, value + valueDiff);
        }

        // ============== PQW 数字IO 系列函数 ==============
        private bool PQW16SetOffAll(TestItem item)
        {
            // 实现16位数字输出设置逻辑
            Global.List16ChPQW[stationIndex].OffAll();
            return true;
        }

        private bool PQW16SetDO(TestItem item)
        {
            // 实现16位数字输出设置逻辑
            int channel = int.Parse(item.Param3);
            int value = int.Parse(item.Param4);
            Global.List16ChPQW[stationIndex].SetDO(channel, value == 1);
            return true;
        }

        public static bool Station1ComFind { get; set; } = false;
        public static bool NeedWaitStation1PowerEnd { get; set; } = false;
        public static bool NeedWaitStation2PowerEnd { get; set; } = false;
        public static AutoResetEvent Station1PowerEndEvent { get; set; }
        public static AutoResetEvent Station2PowerEndEvent { get; set; }

        private bool PQW16SetDOForPower(TestItem item)
        {
            int channel = int.Parse(item.Param3);
            int value = int.Parse(item.Param4);
            string com1 = "COM" + Config.Params["IP20耦合器测试工位1串口"];
            string com2 = "COM" + Config.Params["IP20耦合器测试工位2串口"];

            if (stationIndex == 0)
            {
                ActionSetLog.Invoke("耦合器供电开始");
                //Mylog.Info("工位1耦合器供电开始");
                Global.List16ChPQW[stationIndex].SetDO(channel, value == 1);
                //Mylog.Info("工位1耦合器供电结束");
                ActionSetLog.Invoke("耦合器供电结束");
                Stopwatch sw = Stopwatch.StartNew();
                while (sw.ElapsedMilliseconds < 10000)
                {
                    string[] ports = SerialPort.GetPortNames();

                    // find com15
                    if (ports.Contains(com1))
                    {
                        ActionSetLog.Invoke($"耦合器{com1}识别到");
                        //Mylog.Info($"工位1耦合器{com1}识别到");
                        Station1ComFind = true;
                        Thread.Sleep(5000);
                        Station1PowerEndEvent?.Set();
                        if (NeedWaitStation2PowerEnd)
                        {
                            ActionSetLog.Invoke($"等待工位2供电识别开始");
                            Station2PowerEndEvent?.WaitOne();
                            ActionSetLog.Invoke($"等待工位2供电识别结束");
                        }
                        return true;
                    }
                    Thread.Sleep(100);
                }
                ActionSetLog.Invoke($"耦合器{com1}未识别到");
                //Mylog.Info($"工位1耦合器{com1}未识别到");
                Station1ComFind = false;
                Station1PowerEndEvent?.Set();

                throw new DriveNotFoundException($"{com1}未识别到");
            }
            else
            {
                if (NeedWaitStation1PowerEnd)
                {
                    Station1PowerEndEvent?.WaitOne();
                }

                string[] ports = SerialPort.GetPortNames();
                if (ports.Contains(com1))
                {
                    Station1ComFind = true;
                }
                else
                {
                    Station1ComFind = false;
                }

                ActionSetLog.Invoke("耦合器供电开始");
                //Mylog.Info("工位2耦合器供电开始");
                Global.List16ChPQW[stationIndex].SetDO(channel, value == 1);
                //Mylog.Info("工位2耦合器供电结束");
                ActionSetLog.Invoke("耦合器供电结束");

                Stopwatch sw = Stopwatch.StartNew();
                while (sw.ElapsedMilliseconds < 10000)
                {
                    ports = SerialPort.GetPortNames();

                    if (Station1ComFind)
                    {
                        // find com16
                        if (ports.Contains(com2))
                        {
                            //Mylog.Info($"工位2耦合器{com2}识别到");
                            ActionSetLog.Invoke($"耦合器{com2}识别到");
                            Station2PowerEndEvent?.Set();
                            Global.IP20Factorys[stationIndex].SetPort(byte.Parse(Config.Params["IP20耦合器测试工位2串口"]));
                            Global.IP20Ports[stationIndex] = "COM" + Config.Params["IP20耦合器测试工位2串口"];
                            return true;
                        }
                    }
                    else
                    {
                        // find com15
                        if (ports.Contains(com1))
                        {
                            //Mylog.Info($"工位2耦合器{com1}识别到");
                            ActionSetLog.Invoke($"耦合器{com1}识别到");

                            Global.IP20Factorys[stationIndex].SetPort(byte.Parse(Config.Params["IP20耦合器测试工位1串口"]));
                            Global.IP20Ports[stationIndex] = "COM" + Config.Params["IP20耦合器测试工位1串口"];
                            return true;
                        }
                    }

                    Thread.Sleep(100);
                }

                if (Station1ComFind)
                {
                    ActionSetLog.Invoke($"耦合器{com2}未识别到");
                    //Mylog.Info($"工位2耦合器{com2}未识别到");
                    Station2PowerEndEvent?.Set();
                    throw new DriveNotFoundException($"{com2}未识别到");
                }
                else
                {
                    ActionSetLog.Invoke($"耦合器{com1}未识别到");
                    //Mylog.Info($"工位2耦合器{com1}未识别到");
                    throw new DriveNotFoundException($"{com1}未识别到");
                }
            }
        }

        private bool PQW16GetDI(TestItem item)
        {
            // 实现16位数字输入读取逻辑
            int channel = int.Parse(item.Param3);
            bool cmpvalue = int.Parse(item.Param4) == 1;
            var value = Global.List16ChPQW[stationIndex].GetDI(channel);
            return value == cmpvalue;
        }

        private bool PQW8SetOffAll(TestItem item)
        {
            // 实现8位数字输出设置逻辑
            Global.List8ChPQW[stationIndex].OffAll();
            return true;
        }

        private bool PQW8SetDO(TestItem item)
        {
            // 实现8位数字输出设置逻辑
            int channel = int.Parse(item.Param3);
            int value = int.Parse(item.Param4);
            Global.List8ChPQW[stationIndex].SetDO(channel, value == 1);
            return true;
        }

        private bool PQW8GetDI(TestItem item)
        {
            // 实现8位数字输入读取逻辑
            int channel = int.Parse(item.Param3);
            var value = Global.List8ChPQW[stationIndex].GetDI(channel);
            return value;
        }

        // ============== JX1000 传感器 系列函数 ==============
        private bool JX1000GetLight(TestItem item)
        {
            // 实现光照度测量逻辑
            int channel = int.Parse(item.Param3);
            int value;
            if (stationIndex == 0)
            {
                value = Global.JX1000.ReadH(channel, JX1000_Type.Light);
            }
            else
            {
                value = Global.JX1000.ReadH(channel + 20, JX1000_Type.Light);
            }
            item.Message = $"亮度{value}";
            return CompareValue(item, value);
        }

        private bool JX1000GetLightBulin(TestItem item)
        {
            // 实现光照度测量逻辑
            int channel = int.Parse(item.Param3);
            int times = int.Parse(item.Param4);
            int delay = int.Parse(item.Param5);
            int value;
            string valuestr = "";
            List<int> values = new List<int>();

            int errTimes = 0;
            for (int i = 0; i < times; i++)
            {
                try
                {
                    if (errTimes > 3)
                    {
                        throw new Exception("JX1000采集亮度异常");
                    }
                    if (stationIndex == 0)
                    {
                        value = Global.JX1000.ReadH(channel, JX1000_Type.Light);
                    }
                    else
                    {
                        value = Global.JX1000.ReadH(channel + 20, JX1000_Type.Light);
                    }
                    values.Add(value);
                }
                catch (Exception ex)
                {
                    errTimes++;
                    Mylog.Error(ex);
                }

                Delay(delay);
            }
            List<bool> bools = new List<bool>();
            for (int i = 0; i < values.Count; i++)
            {
                valuestr += $"{values[i]},";
                var cmpRet = CompareValue(item, values[i]);
                bools.Add(cmpRet);
            }

            item.Message = $"实测值{valuestr.TrimEnd(',')}";
            //if (bools.Contains(true) && bools.Contains(false))
            if (bools.Contains(true))
            {
                return true;
            }

            return false;
        }

        private bool JX1000GetColor(TestItem item)
        {
            // 实现颜色测量逻辑
            int channel = int.Parse(item.Param3);
            int value;
            if (stationIndex == 0)
            {
                value = Global.JX1000.ReadH(channel, JX1000_Type.Color);
            }
            else
            {
                value = Global.JX1000.ReadH(channel + 20, JX1000_Type.Color);
            }
            item.Message = $"色相{value}";
            return CompareValue(item, value);
        }

        private bool JX1000GetColorBulin(TestItem item)
        {
            // 实现颜色测量逻辑

            int channel = int.Parse(item.Param3);
            int times = int.Parse(item.Param4);
            int delay = int.Parse(item.Param5);
            int value;
            string valuestr = "";
            List<int> values = new List<int>();
            int errTimes = 0;
            for (int i = 0; i < times; i++)
            {
                try
                {
                    if (errTimes > 3)
                    {
                        throw new Exception("JX1000采集亮度异常");
                    }
                    if (stationIndex == 0)
                    {
                        value = Global.JX1000.ReadH(channel, JX1000_Type.Color);
                    }
                    else
                    {
                        value = Global.JX1000.ReadH(channel + 20, JX1000_Type.Color);
                    }
                    values.Add(value);
                }
                catch (Exception ex)
                {
                    errTimes++;
                    Mylog.Error(ex);
                }
            }
            List<bool> bools = new List<bool>();
            for (int i = 0; i < values.Count; i++)
            {
                valuestr += $"{values[i]},";
                var cmpRet = CompareValue(item, values[i]);
                bools.Add(cmpRet);
            }

            item.Message = $"色相值:{valuestr.TrimEnd(',')}";
            return bools.Contains(true);
        }

        private bool JX1000GetFreq(TestItem item)
        {
            // 实现频率测量逻辑
            int channel = int.Parse(item.Param3);
            int value;
            if (stationIndex == 0)
            {
                value = Global.JX1000.ReadH(channel, JX1000_Type.Frequency);
            }
            else
            {
                value = Global.JX1000.ReadH(channel + 20, JX1000_Type.Frequency);
            }
            item.Message = $"频率{value}";
            return CompareValue(item, value);
        }

        private bool JX1000GetFreqBulin(TestItem item)
        {
            // 实现频率测量逻辑
            int channel = int.Parse(item.Param3);
            int times = int.Parse(item.Param4);
            int value;
            for (int i = 0; i < 10; i++)
            {
                if (stationIndex == 0)
                {
                    value = Global.JX1000.ReadH(channel, JX1000_Type.Color);
                }
                else
                {
                    value = Global.JX1000.ReadH(channel + 20, JX1000_Type.Color);
                }
                var cmpRet = CompareValue(item, value);
                if (cmpRet)
                {
                    return true;
                }
            }
            item.Message = $"识别{times}次未满足条件";
            return false;
        }

        // ============== 通用模拟量测量函数 ==============
        private bool AnalogMeasVol(TestItem item)
        {
            // 实现通用电压测量逻辑
            List<int> channels = item.Param3.Split(',')
                          .Select(s => int.Parse(s.Trim()))
                          .ToList();

            int devIndexOffset = stationIndex == 1 ? 3 : 0;
            double valueProcess = 1;
            if (!string.IsNullOrEmpty(item.Param4))
            {
                valueProcess = double.Parse(item.Param4);
            }

            List<double> values = new List<double>();
            for (int i = 0; i < 3; i++)
            {
                var value = Global.ListVoltageCards[i + devIndexOffset].GetValue();

                values.AddRange(value.Select(x => x * valueProcess));
                Delay(10);
            }

            List<double> errorDiff = new List<double>();
            for (int i = 0; i < 19; i++)
            {
                errorDiff.Add(double.Parse(GetParams($"工位{stationIndex + 1}电压采集卡通道{i + 1}读值误差")));//工位1电压采集卡通道1读值误差
            }

            item.Message = "";
            bool totalResult = true;
            string message = "实测电压为";
            foreach (var ch in channels)
            {
                message += $"{values[ch - 1] + errorDiff[ch - 1]}V,";
                bool result = CompareValue(item, values[ch - 1] + errorDiff[ch - 1]);
                if (!result)
                {
                    totalResult = false;
                }
            }
            item.Message = message.TrimEnd(',');
            return totalResult;
        }

        private bool AnalogMeasCur(TestItem item)
        {
            // 实现通用电流测量逻辑
            List<int> channels = item.Param3.Split(',')
                          .Select(s => int.Parse(s.Trim()))
                          .ToList();

            int devIndexOffset = stationIndex == 1 ? 5 : 0;

            List<double> values = new List<double>();
            for (int i = 0; i < 3; i++)
            {
                var value = Global.ListCurrentCards[i + devIndexOffset].GetValue();
                values.AddRange(value);
                Delay(10);
            }

            List<double> errorDiff = new List<double>();
            for (int i = 0; i < 19; i++)
            {
                errorDiff.Add(double.Parse(GetParams($"工位{stationIndex + 1}电压采集卡通道{i + 1}读值误差")));//工位1电压采集卡通道1读值误差
            }

            item.Message = "";
            bool totalResult = true;
            string message = "实测电流为";
            foreach (var ch in channels)
            {
                var cur = Math.Round(values[ch - 1] / 249 * 1000 + errorDiff[ch - 1], 3);
                message += $"{cur}mA,";
                bool result = CompareValue(item, cur);
                if (!result)
                {
                    totalResult = false;
                }
            }
            item.Message = message.TrimEnd(',');
            return totalResult;
        }

        private bool AnalogMeasCurNPN(TestItem item)
        {
            // 实现通用电流测量逻辑
            List<int> channels = item.Param3.Split(',')
                          .Select(s => int.Parse(s.Trim()))
                          .ToList();

            int devIndexOffset = stationIndex == 1 ? 5 : 0;

            List<double> values = new List<double>();
            for (int i = 3; i < 5; i++)
            {
                var value = Global.ListCurrentCards[i + devIndexOffset].GetValue();
                values.AddRange(value);
                Delay(10);
            }

            List<double> errorDiff = new List<double>();
            for (int i = 0; i < 16; i++)
            {
                errorDiff.Add(double.Parse(GetParams($"工位{stationIndex + 1}电流采集卡(NPN)通道{i + 1}读值误差")));//工位1电压采集卡通道1读值误差
            }

            item.Message = "";
            bool totalResult = true;
            string message = "实测电流为";
            foreach (var ch in channels)
            {
                var cur = Math.Round(values[ch - 1] / 249 * 1000 + errorDiff[ch - 1], 3);
                message += $"{cur}mA,";
                bool result = CompareValue(item, cur);
                if (!result)
                {
                    totalResult = false;
                }
            }
            item.Message = message.TrimEnd(',');
            return totalResult;
        }

        private void Delay(int millsecond)
        {
            Stopwatch sw = Stopwatch.StartNew();
            while (sw.ElapsedMilliseconds < millsecond)
            {
                if (IsBreak)
                {
                    throw new Exception("急停/安全光幕触发");
                }
                Thread.Sleep(1);
            }
        }

        private bool Delay(TestItem item)
        {
            Delay(int.Parse(item.Param3));
            return true;
        }

        private bool DL3021ASetMode(TestItem item)
        {
            DL3021A_Mode mode = (DL3021A_Mode)int.Parse(item.Param3);
            Global.ListDL3021A[stationIndex].SetMode(mode);
            return true;
        }

        private bool DL3021ASetVol(TestItem item)
        {
            var value = double.Parse(item.Param3);

            if (value <= (int)DL3021A_Range.CV_15V)
            {
                Global.ListDL3021A[stationIndex].SetRang(DL3021A_Mode.CV, DL3021A_Range.CV_15V);
            }
            else if (value <= (int)DL3021A_Range.CV_150V)
            {
                Global.ListDL3021A[stationIndex].SetRang(DL3021A_Mode.CV, DL3021A_Range.CV_150V);
            }
            else
            {
                throw new Exception("超出最大量程");
            }

            Global.ListDL3021A[stationIndex].SetVoltageCV(value);
            return true;
        }

        private bool DL3021ASetCur(TestItem item)
        {
            var value = double.Parse(item.Param3);

            if (value <= (int)DL3021A_Range.CC_4A)
            {
                Global.ListDL3021A[stationIndex].SetRang(DL3021A_Mode.CC, DL3021A_Range.CC_4A);
            }
            else if (value <= (int)DL3021A_Range.CC_40A)
            {
                Global.ListDL3021A[stationIndex].SetRang(DL3021A_Mode.CC, DL3021A_Range.CC_40A);
            }
            else
            {
                throw new Exception("超出最大量程");
            }
            Global.ListDL3021A[stationIndex].SetCurrentCC(value);
            return true;
        }

        private bool DL3021ASetRes(TestItem item)
        {
            var value = double.Parse(item.Param3);

            if (value <= (int)DL3021A_Range.CR_15)
            {
                Global.ListDL3021A[stationIndex].SetRang(DL3021A_Mode.CR, DL3021A_Range.CR_15);
            }
            else if (value <= (int)DL3021A_Range.CR_15000)
            {
                Global.ListDL3021A[stationIndex].SetRang(DL3021A_Mode.CR, DL3021A_Range.CR_15000);
            }
            else
            {
                throw new Exception("超出最大量程");
            }
            Global.ListDL3021A[stationIndex].SetResCR(value);
            return true;
        }

        private bool DL3021ASetPow(TestItem item)
        {
            var value = double.Parse(item.Param3);
            Global.ListDL3021A[stationIndex].SetPowCP(value);
            return true;
        }

        private bool DL3021AMeasVol(TestItem item)
        {
            var value = Global.ListDL3021A[stationIndex].MeasVoltage();
            item.Message = $"负载电压{value}V";
            return CompareValue(item, value);
        }

        private bool DL3021AMeasCur(TestItem item)
        {
            var value = Global.ListDL3021A[stationIndex].MeasCurrent();
            item.Message = $"负载电流{value}A";

            return CompareValue(item, value);
        }

        private bool DL3021AMeasPow(TestItem item)
        {
            var value = Global.ListDL3021A[stationIndex].MeasPow();
            item.Message = $"功率={value}W";
            return CompareValue(item, value);
        }

        private bool DL3021ASetStatus(TestItem item)
        {
            var value = int.Parse(item.Param3);
            Global.ListDL3021A[stationIndex].SetOutputStatus(value == 1);
            return true;
        }
    }
}